package controller;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.util.ArrayList;
import java.util.List;

import model.UploadItem;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpVersion;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.params.HttpParams;
import org.apache.http.util.EntityUtils;

import utils.CountingMultipartEntity;
import utils.CountingMultipartEntity.ProgressListener;
import utils.ItemUploadResponseHandler;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.widget.ProgressBar;
import app.cloudstringers.Home;
import app.cloudstringers.R;
import define.API;
import define.Constants;
import define.Key;
import define.MobileAlbum;

@SuppressWarnings("deprecation")
public class UploadItemAsync extends AsyncTask<String, Integer, Boolean> {
	/**
	 * String section
	 */
	private static final String TAG = UploadItemAsync.class.getSimpleName();

	// All static variables 
	private String GLOBAL_ID = null;
	private String SIZE = null;
	private long SUM_OF_FILE_SIZES = 0;
	private String USER_NAME = null;

	/**
	 * View section
	 */
	public static Dialog mDialog = null;
	private ProgressBar mPbUploadFile = null;

	/**
	 * The Other Tools
	 */
	private Context context;

	// private String TOAST = null;

	public UploadItemAsync(Context context) {
		this.context = context;

		// Set boolean to allow the user switch the other tab or not
		// Because if the user left, uploading progress will end
		MobileAlbum.CAN_LEAVE = false;
	}

	@Override
	protected Boolean doInBackground(String... params) {
		USER_NAME = params[0];
		GLOBAL_ID = params[1];
		SIZE = params[2];

		try {
			/**
			 * Call Generate XML API
			 */
			callGenerateXmlApi();

			/**
			 * Call Clip Upload API
			 */
			callClipUploadApi(API.CLIP_UPLOAD);

			if (MobileAlbum.CAN_LEAVE) {
				return false;
			}

			return true;
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
			return false;
		} catch (ClientProtocolException e) {
			e.printStackTrace();
			return false;
		} catch (ConnectTimeoutException e) {
			e.printStackTrace();
			return false;
		} catch (SocketException e) {
			e.printStackTrace();
			return false;
		} catch (SocketTimeoutException e) {
			e.printStackTrace();
			return false;
		} catch (IOException e) {
			e.printStackTrace();
			return false;
		}
	}

	@Override
	protected void onPreExecute() {
		super.onPreExecute();

		// show progress dialog
		if (mPbUploadFile == null) {
			View view = ((Activity) context).getLayoutInflater().inflate(
					R.layout.dialog_progress_bar_upload_file, null);
			mPbUploadFile = (ProgressBar) view
					.findViewById(R.id.pb_upload_file);

			mDialog = new Dialog(context);
			mDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
			mDialog.setContentView(view);

			Constants.utils.initialFullWidthScreenDialog(mDialog);

			mDialog.show();
		}
	}

	@Override
	protected void onProgressUpdate(Integer... values) {
		mPbUploadFile.setProgress(values[0]);

		super.onProgressUpdate(values);
	}

	@Override
	protected void onPostExecute(Boolean result) {
		super.onPostExecute(result);

		// Toast.makeText(context, TOAST, Toast.LENGTH_SHORT).show();

		if (!result) {
			if (!MobileAlbum.CAN_LEAVE) {
				Constants.utils.showConnectionTimeoutDialog(context,
						((Activity) context).getClass());
			}
		}

		// Hide progress dialog
		if (mDialog != null && mDialog.isShowing()) {
			mDialog.dismiss();
			mDialog = null;
		}

		// Set boolean to allow the user switch the other tab or not
		// Because if the user left, uploading progress will end
		MobileAlbum.CAN_LEAVE = true;
	}

	/**
	 * Basic methods
	 * 
	 * @throws IOException
	 * @throws ClientProtocolException
	 */
	private void callClipUploadApi(String url) throws ClientProtocolException,
			IOException {

		// Get sum of file sizes of all item
		for (Long item : Home.mLlSumOfFileSizes) {
			SUM_OF_FILE_SIZES += item;
		}

		HttpParams mHttpParams = new BasicHttpParams();
		HttpPost mHttpPost = new HttpPost(url);
		
//		SchemeRegistry schReg = new SchemeRegistry();
//	    schReg.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
//	    schReg.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));
//	    ClientConnectionManager conMgr = new ThreadSafeClientConnManager(mHttpParams, schReg);
	    
		DefaultHttpClient mHttpClient = new DefaultHttpClient(mHttpParams);

		CountingMultipartEntity mMultipartEntity = new CountingMultipartEntity(
				HttpMultipartMode.BROWSER_COMPATIBLE, new ProgressListener() {

					@Override
					public void transferred(String num) {
						publishProgress(Integer.valueOf(Math.round(Float
								.valueOf((Float.valueOf(num) / Float
										.valueOf(SUM_OF_FILE_SIZES)) * 100))
								+ ""));
					}
				});

		mHttpParams.setParameter(CoreProtocolPNames.PROTOCOL_VERSION,
				HttpVersion.HTTP_1_1);

		// Add user_email, global_id, sum of file sizes
		mMultipartEntity.addPart(Key.KEY_USER_EMAIL, new StringBody(USER_NAME));

		mMultipartEntity.addPart(MobileAlbum.KEY_SUM_OF_FILE_SIZES,
				new StringBody(String.valueOf(SUM_OF_FILE_SIZES)));
		mMultipartEntity.addPart(Key.KEY_GLOBAL_ID, new StringBody(GLOBAL_ID));

		// Add up_file = data
		for (UploadItem uploadItem : Home.mLlItems) {
			mMultipartEntity.addPart(MobileAlbum.KEY_UP_FILE, new FileBody(
					new File(uploadItem.getPath())));
		}

		mHttpPost.setEntity(mMultipartEntity);

		String XML = mHttpClient.execute(mHttpPost,
				new ItemUploadResponseHandler());

		Log.i(TAG, "callClipUploadApi" +XML);

		// TOAST = XML;
		// TODO
		// If receive
		// "{state:'cancelled',error:'kunting_sgp@trek2000.com.sg;2576225:2.576225;000400010007;File VID_20140123_135757.mp4 exists'}"
		// delay the upload later until the previous video complete converting
		// If receive "{state:'cancelled',error:'over space limit'}"
		// the account has used up space, 100% storage used
	}

	private void callGenerateXmlApi() throws ClientProtocolException,
			IOException {
		HttpClient mHttpClient = new DefaultHttpClient();
		HttpPost mHttpPost = new HttpPost(API.GENERATE_XML);
		List<NameValuePair> mNameValue = new ArrayList<NameValuePair>();

		mNameValue.add(new BasicNameValuePair(Key.KEY_USER_EMAIL, USER_NAME));
		mNameValue.add(new BasicNameValuePair(Key.KEY_GLOBAL_ID, GLOBAL_ID));
		mNameValue.add(new BasicNameValuePair(Key.KEY_NUM_VIDEOS, SIZE));

		// XML_info : File name with extension, file size, lastModifiedDateTime
		StringBuilder mSb = new StringBuilder();

		for (UploadItem uploadItem : Home.mLlItems) {
			mSb.append(uploadItem.getFileName() + ","
					+ uploadItem.getTotalSize() + ","
					+ uploadItem.getLastModifiedDate() + ","
					+ MobileAlbum.SEPERATOR);
		}

		mNameValue
				.add(new BasicNameValuePair(Key.KEY_XML_INFO, mSb.toString()));

		mHttpPost.setEntity(new UrlEncodedFormEntity(mNameValue));
		HttpResponse mHttpResponse = mHttpClient.execute(mHttpPost);
		HttpEntity mHttpEntity = mHttpResponse.getEntity();
		String XML = EntityUtils.toString(mHttpEntity);

		Log.i(TAG, "callGenerateXmlApi" + XML);
	}
}
